import 'package:freedom/const/game_const.dart';
import 'package:freedom/util/data_type.dart';

class MessageContent<T> {
  // 公共语音
  static const int MT_VOICE = 1;

  // 公共聊天
  static const int MT_CHAT = 2;

  // 游戏内部事件
  static const int MT_ACT = 3;
  // 谁发出的
  int? messageFromUid;
  int? messageToUid;
  // 发送给指定人
  int? target;
  // 消息类型  如上  语音 事件 聊天
  int? type;
  T? body;
  // 当前房间号版本
  int synVersion;
  // 具体内容
  dynamic bodyContent;

  MessageContent(
      {this.type = MessageContent.MT_ACT,
      this.target,
      this.messageFromUid,
      this.body,
      this.synVersion = 0,
      this.messageToUid,
      this.bodyContent}) {
    assert(T != AbstractMessage || T == List<AbstractMessage>,
        'T must be either AbstractMessage or List<AbstractMessage>');
  }

  factory MessageContent.copyWith(MessageContent userState, T body) {
    return MessageContent<T>(
        messageFromUid: userState.messageFromUid,
        type: userState.target,
        bodyContent: userState.bodyContent,
        body: body);
  }

  factory MessageContent.fromJson(Map<String, dynamic>? jsonRes) {
    if (jsonRes == null) {
      return MessageContent();
    }
    return MessageContent(
        messageFromUid: asT<int>(jsonRes['messageFromUid']),
        messageToUid: asT<int>(jsonRes['messageToUid']),
        target: asT<int>(jsonRes['target']),
        type: asT<int>(jsonRes['type']),
        synVersion: asT<int>(jsonRes['synVersion']) ?? 0,
        body: jsonRes['body'],
        bodyContent: jsonRes['body']);
  }

  dynamic toJson() {
    var bodyData;
    if (body is List) {
      bodyData = [];
      (body as List<AbstractMessage>).forEach((action) {
        bodyData.add(action.toJson());
      });
    } else if (body is AbstractMessage) {
      bodyData = (body as AbstractMessage).toJson();
    } else {
      bodyData = this.body;
    }
    return <String, dynamic>{
      "messageFromUid": messageFromUid,
      "target": target,
      "type": type,
      "body": bodyData,
    };
  }
}

class VoiceMessage {
  String? cmd;
  dynamic msg;
  List<int> correlationUIds = [];
  VoiceMessage({this.cmd, this.msg, this.correlationUIds = const []});

  factory VoiceMessage.fromJson(Map<String, dynamic>? jsonRes) {
    if (jsonRes == null) {
      return VoiceMessage();
    }
    List<int> correlationUIds = [];
    List userIdList =
        jsonRes["correlationUIds"] is List ? jsonRes["correlationUIds"] : [];
    for (var item in userIdList) {
      correlationUIds.add(item);
    }
    return VoiceMessage(
        cmd: asT<String>(jsonRes['cmd']),
        msg: asT<dynamic>(jsonRes['msg']),
        correlationUIds: correlationUIds);
  }
}

abstract class AbstractMessage {
  Map<String, dynamic> toJson();
}

class MahjongMessage extends AbstractMessage {
  // 事件类型
  String? type;
  // 出牌信息
  int? cardCode;
  int? cardType;
  int exeActionUid = 0;
  String? data;
  // 交换信息
  List<int>? swapCard;
  // action 事件更新
  List<String>? actionSet;
  String? actionStr;
  int? sourceBySeq;
  double sleep = 0;

  MahjongMessage(
      {this.type,
      this.cardCode,
      this.actionSet,
      this.data,
      this.actionStr,
      this.sourceBySeq,
      this.cardType,
      this.exeActionUid = 0,
      this.sleep = 0,
      this.swapCard});

  factory MahjongMessage.fromJson(Map<String, dynamic>? jsonRes) {
    if (jsonRes == null) {
      return MahjongMessage();
    }
    List<String> actionSetTemp = jsonRes['actionSet'] is List ? <String>[] : [];
    // 避免空指针
    for (final dynamic item in jsonRes['actionSet'] ?? []) {
      if (asT<String>(item) != null) {
        actionSetTemp.add(item);
      }
    }

    List<int> swapCardTemp = jsonRes['swapCard'] is List ? <int>[] : [];
    // 避免空指针
    for (final dynamic item in jsonRes['swapCard'] ?? []) {
      if (asT<int>(item) != null) {
        swapCardTemp.add(item);
      }
    }
    return MahjongMessage(
        type: asT<String>(jsonRes['type']),
        cardCode: asT<int>(jsonRes['cardCode']),
        actionStr: asT<String>(jsonRes['actionStr']),
        data: asT<String>(jsonRes['data']),
        cardType: asT<int>(jsonRes['cardType']),
        exeActionUid: asT<int>(jsonRes['exeActionUid']) ?? 0,
        sleep: asT<double>(jsonRes['sleep']) ?? 0,
        sourceBySeq: asT<int>(jsonRes['sourceBySeq']),
        swapCard: swapCardTemp,
        actionSet: actionSetTemp);
  }

  @override
  Map<String, dynamic> toJson() => <String, dynamic>{
        "type": type,
        "cardCode": cardCode,
        "swapCard": swapCard
      };
}

class ChatMessage extends AbstractMessage {
  String? text;
  int messageFromUid = 0;
  int type;
  int? index;
  int? animationCode;

  factory ChatMessage.fromJson(Map<String, dynamic>? jsonRes) {
    if (jsonRes == null) {
      return ChatMessage();
    }
    return ChatMessage(
        text: asT<String>(jsonRes['text']),
        index: asT<int>(jsonRes['index']),
        type: asT<int>(jsonRes['type']) ?? MessageTypeConst.chart,
        messageFromUid:
            asT<int>(jsonRes['messageFromUid']) ?? MessageTypeConst.chart);
  }

  ChatMessage({this.text, this.type = 0, this.index, this.messageFromUid = 0});

  @override
  Map<String, dynamic> toJson() =>
      <String, dynamic>{"text": text, "type": type, "index": index};
}
